/**
 * create by young (young2f@outlook.com) on 2023/4/16
 */
'use strict';
const base = require('../base/serviceBase');
const _ = require('lodash');
const _stringUtils = require('../utils/stringUtils');
const table = 'SalesOrder';
const moment = require('moment');
const { getTax } = require('../base/serviceBase');
const { assignWith } = require('lodash');
module.exports = class extends base {

  /**

   * @returns {Promise<{status: string, result: *}>}
   * @param material
   * @param tenantCode
   */
  async usedMaterial(material, tenantCode) {
    const { ctx } = this;
    const { usedMaterialRecord, salesOrderCode } = material;
    _.map(usedMaterialRecord, async record => {
      console.log('usedMaterialRecord', record);
      const { _useCount, pmLotId } = record;
      record.salesOrderCode = salesOrderCode;
      record.useCount = _useCount;
      record.recordId = 'MUD' + moment()
        .format('YYYYMMDDHHmmss');
      delete record._id;
      const usedRes = await ctx.app.dbs.insert('ProcureLotUsed', record);
      const res1 = await ctx.app.dbs.updateOne('ProcureMaterialRecord', {
        pmLotId,
        tenantCode
      }, { $inc: { useCount: _useCount } });
      const res2 = await ctx.app.dbs.updateOne('Material', {
        code: material.code,
        tenantCode
      }, { $inc: { procureCount: -_useCount } });
    });
  }

  /**
   * {

   * @param body
   * @returns {Promise<{status: string, result: *}>}
   */
  async createOrder(body) {
    const { ctx, service } = this;
    const {
      code,
      tenantCode,
      tenantName,
      createUser,
      createUsername,
      customer,
      address,
      division,
      prods = [],
      contacts,
      contactsPhone,
      createdTs, amount, taxRate
    } = body;

    body.tax = this.getTax(amount, taxRate);
    delete body._id;
    let laborFeeTotal = 0;
    // console.log('create sales order body', body);

    _.map(prods, async prod => {
      const { laborFee } = prod;
      laborFeeTotal += laborFee;
    });
    body.laborFeeTotal = laborFeeTotal;
    body.orderCode = code;
    const result = await ctx.app.dbs.insert('SalesOrder', body);
    _.map(prods, async prod => {
      const { spLotId, prodCode = '' } = prod;
      prod.salesOrderCode = code;
      prod.tenantCode = tenantCode;
      prod.customer = customer;
      prod.division = division;
      prod.spLotId = spLotId ? spLotId : 'SPD' + moment()
        .format('YYYYMMDDHHmmss');
      // const res = await this.createSalesProd(prod);

      /**
       * 占用库存
       */
      delete prod._id;
      const res1 = await this.usedLot(prod);

      const result = await ctx.app.dbs.insert('SalesProdRecord', prod);
      await this.addProdNumber(prodCode);
    });


    const custom = await ctx.app.dbs.findOne('Customer', { tenantCode, name: customer });
    if (!custom) {
      const code = _stringUtils.getCode('CUS');
      body.customerCode = code;
      const custom = await ctx.app.dbs.insert('Customer', {
        code,
        name: customer,
        tenantCode,
        tenantName,
        createUser,
        createUsername,
        customer,
        address,
        contacts,
        contactList: !address && !contacts && !contactsPhone ? undefined : [ {
          address, contacts, contactsPhone,
          code: 'ADD' + Date.now()
            .valueOf()
        } ],
        createdTs
      });
    }
    // delete body.prods;


//    const result1 = await service['outboundService'].createOutboundOrder(body);
    const historyRes = await ctx.app.dbs.insert('History', {
      table,
      name: '新建订单',
      code,
      tenantCode,
      tenantName,
      createUser,
      createUsername,
      createdTs,
      newData: body
    });
    return { status: 'ok', result };
  }

  /**
   * 产品编号要递增
   * @param prodCode
   * @returns {Promise<void>}
   */
  async addProdNumber(prodCode) {
    const list = prodCode.split('-');
    if (list.length === 2) {
      const temp = await this.app.model['ProdNumber'].updateOne({ code: list[0] }, { $inc: { number: 1 } }, { upsert: true });
    }
  }

  /**
   * 物料占用时，查找可用的采购物料批次
   * @param material
   * @returns {Promise<{status: string, result: *[]}>}
   */
  async findUsedMaterialRecord(material) {
    /**
     * 占用采购物料批次
     * 1、不需要检查物料是否有采购批次，在物料选择时已经检查过了
     * 2、检查最新的采购单物料，是否满足数量要求，如果满足，返回
     * 3、轮询物料采购记录，按订单数量进行占用
     */
    const { ctx } = this;
    let { tenantCode, code, materialCount, salesOrderCode } = material;

    /**
     * 如果第一条数量大于订单数量
     */
    const res = await ctx.app.dbs.findOne('ProcureMaterialRecord', { tenantCode, code });
    // console.log('ProcureMaterialRecordd', res,tenantCode, code);

    if (res) {
      const { count = 0, procureOrderCode } = res;
      const res1 = await ctx.app.dbs.find('ProcureLotUsed', { tenantCode, procureOrderCode });
      let _useCount = 0;
      _.map(res1, async prod => {
        const { useCount = 0 } = prod;
        _useCount += useCount;
      });
      if ((count - _useCount) > materialCount) {
        console.log('第一条数量大于订单数量');
        res.useCount = _useCount;
        res._useCount = materialCount;
        //  const res = await ctx.app.dbs.insert('CacheProcureLotUsed', cache);
        return { status: 'ok', result: [ res ] };
      }
    }

    /**
     * 占用多个物料批次
     */
    const result = [];
    const list = await ctx.app.dbs.find('ProcureMaterialRecord', { tenantCode, code });
    for (const record of list) {
      const { count, useCount, pmLotId, procureOrderCode } = record;
      const res1 = await ctx.app.dbs.find('ProcureLotUsed', { tenantCode, });
      let _useCount = 0;
      _.map(res1, async prod => {
        const { useCount = 0 } = prod;
        _useCount += useCount;
      });
      const _count = count - _useCount;
      if (_count > 0) {
        console.log('count数量：', count, 'useCount', useCount);
        const _count = count - useCount;//可用的数量
        console.log('需求数量：', materialCount, '可用数量', _count);
        materialCount -= _count;
        console.log('计算后数量：', _count, materialCount);
        if (materialCount > 0) {
          record._useCount = _count;
          res.useCount = _useCount;
          //    const res = ctx.app.dbs.insert('CacheProcureLotUsed', cache);
          result.push(record);
        } else {

          record._useCount = materialCount + _count;
          res.useCount = _useCount;
          //  const res = ctx.app.dbs.insert('CacheProcureLotUsed', cache);
          result.push(record);
        }
      }
    }
    console.log('findUsedMaterialRecord', result);
    return { status: 'ok', result };
  }

  getValue = (_type, value, key) => {
    if (_type === 'date') {
      console.log('日期', value, key);
      if (key.includes('.')) {
        console.log('下一级日期，需要转换');
        return {
          $gte: moment(value[0])
            .startOf('day')
            .valueOf(),
          $lt: new moment(value[1])
            .endOf('day')
            .valueOf()
        };
      }

      // query[key]={$eq:new Date(moment(value).valueOf())}
      return {
        $gte: new Date(moment(value[0])
          .startOf('day')
          .valueOf()),
        $lt: new Date(moment(value[1])
          .endOf('day')
          .valueOf())
      };
    }
    if (_type === 'string' || _type === 'select') {
      if (typeof value === 'string') {
        return { $regex: value };
      } else {
        return value;
      }

    }
    if (_type === 'number') {
      const t = value.charAt(0);
      const number = value.substring(1);
      if (!this.isNumber(number)) {
        throw new Error(`数字查询条件错误：${key},${value} `);
      }
      const _number = parseFloat(number);
      if (t !== '<' && t !== '>' && t !== '=' && this.isNumber(number)) {
        return { $eq: _number };
      } else {
        if (t === '<') {
          return { $lt: _number };
        }
        if (t === '>') {
          return { $gt: _number };
        }
        if (t === '=') {
          return { $eq: _number };
        }
      }
    }
    return undefined;
  };

  async assess(body) {
    const res = await this.findOrderMany(body);
    const { status, result } = res;
    if (status !== 'ok') {
      return { status, result: { amount: 0, count: 0 } };
    }
    let amount = 0,
      count = 0;
    _.map(result, item => {

      amount += item.amount;
      count += item.count;

    });
    return { status: 'ok', result: { amount, count } };
  }

  async findOrderMany(body) {
    const { ctx, service } = this;
    const { tenantCode } = body;
    const query = { tenantCode };
    const { prods = {}, isKP, isFH, createdTs } = body;
    const { materials = {} } = prods;
    delete body['tenantName'];
    delete body['tenantCode'];
    delete body['isDeleted'];
    delete body['prods'];
    delete body['materials'];
    delete body['createdTs'];

    const schema = await service.globalService.getModel({ table: 'SalesOrder' });
    _.map(body, (value, key) => {
      const temp = _.find(schema, (it, k) => {
        return k === key;
      });

      if (temp) {
        const { _type } = temp;
        query[key] = this.getValue(_type, value, key);
      }
    });

    _.map(prods, (value, key) => {
      const temp = _.find(schema.prods, (it, k) => {
        return k === key;
      });

      if (temp) {
        const { _type } = temp;
        const _key = `prods.${key}`;
        query[_key] = this.getValue(_type, value, _key);
      }
    });

    _.map(materials, (value, key) => {
      const temp = _.find(schema.prods.materials, (it, k) => {
        return k === key;
      });

      if (temp) {
        const { _type } = temp;
        const _key = `prods.materials.${key}`;
        query[_key] = this.getValue(_type, value, _key);
      }
    });
    const { key } = body;
    const _key = key ? key : 'createdTs';

    const sort = {};
    sort[_key] = -1;
    delete query['prods.materials'];
    if (isKP && isKP === '已开票') {
      query['prods.invoicingDate'] = { $ne: null };
    }
    if (isKP && isKP === '未开票') {
      query['prods.invoicingDate'] = { $eq: null };
    }
    if (isFH && isFH === '已发货') {
      query['outboundCount'] = { $gt: 0 };
    }
    if (isFH && isFH === '未发货') {
      query['outboundCount'] = { $eq: 0 };
    }
    if (createdTs && createdTs.length > 0) {
      query['createdTs'] = {
        $gte: new Date(moment(createdTs[0])
          .valueOf()),
        $lt: new Date(moment(createdTs[1])
          .valueOf())
      };
    }
    query['isDeleted'] = false;
    console.log('find sales order query', query);
    const res = await ctx.app.dbs.aggregate(table, [
      { $match: { ...query } },
      { $sort: { ...sort } },
    ]);
    const res1 = [];
    _.map(res, item => {
      const { labels } = item;
      _.map(labels, it => {
        _.assign(item, it);
      });
      res1.push(item);
    });
    // console.log('find sales order 1');
    // const array = [];

    // const result = { amount, count, array };
    console.log('find sales order result', res);
    return { status: 'ok', result: res };
  }

  async findOne(body) {
    const { tenantCode, code } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.findOne(table, { tenantCode, code });
    console.log('find sales order body', body);
    const prods = await ctx.app.dbs.find('SalesProdRecord', { tenantCode, salesOrderCode: code });
    let amount = 0;
    _.map(prods, item => {

    });
    return { status: 'ok', result };
  }

  async updateMaterials(body) {
    const {
      tenantCode,
      code,
      prods
    } = body;
    const { ctx, service } = this;
    const oldData = await ctx.app.dbs.findOne(table, { tenantCode, code });
    const oldMaterials = [];

    _.map(oldData.prods, (item) => {
      _.map(item.materials, (it, k) => {
        const { usedProcureMaterialLots } = it;
        oldMaterials.push(...usedProcureMaterialLots);
        console.log('mm', usedProcureMaterialLots);
      });
    });

    _.map(oldMaterials, async (item) => {
      const { materialCount, pmLotId } = item;
      console.log('mm1', pmLotId);
      const res1 = await ctx.app.dbs.updateOne('ProcureMaterialRecord', {
        pmLotId,
        tenantCode
      }, { $inc: { useCount: -materialCount } });
    });
    _.map(prods, (item) => {
      const { materials } = item;
      _.map(materials, async (it, k) => {
        const { usedProcureMaterialLots } = it;
        _.map(usedProcureMaterialLots, async (it, k) => {
          const { materialCount, pmLotId } = it;
          console.log('mm2', it);
          const res1 = await ctx.app.dbs.updateOne('ProcureMaterialRecord', {
            pmLotId,
            tenantCode
          }, { $inc: { useCount: materialCount } });
        });
      });
    });
  }

  async updateOrder(body) {
    console.log('uuuuuu', body);
    const res = await this.deleteOrder(body);
    const result = await this.createOrder(body);
    return { status: 'ok', result };
  }


  async deleteOrder(body) {
    const { tenantCode, code, tenantName, createUser, createUsername, createdTs } = body;
    const { ctx } = this;
    const order = await ctx.app.dbs.findOne(table, { tenantCode, code });
    if (!order) {
      throw new Error('订单已删除');
    }
    if (order.reviewStatus === '同意') {
      throw new Error('更新/删除失败！订单已审核通过！');
    }
    const lots = await ctx.app.dbs.find('OutboundLot', { orderCode: code, tenantCode });
    if (lots && lots.length > 0) {
      throw new Error('更新/删除失败！订单已有发货记录，请删除发货记录后再执行订单删除！');
    }
    const prods = await ctx.app.dbs.find('SalesProdRecord', { tenantCode, salesOrderCode: code });

    _.map(prods, async (prod, k) => {
      console.log('delete prod', prod.spLotId);
      prod.salesOrderCode = code;
      const res = await this.deleteSalesProd(prod);
    });

    const result = await ctx.app.dbs.deleteOne('SalesOrder', { tenantCode, code });

    const history = {
      table,
      name: '删除订单',
      oldData: order,
      tenantCode,
      code,
      tenantName,
      createUser,
      createUsername,
      createdTs
    };
    const historyRes = await ctx.app.dbs.insert('History', history);
    return { status: 'ok', result };
  }

  /**
   * 删除订单中的商品，包括物料占用
   * @returns {Promise<void>}
   * @param ctx
   * @param tenantCode
   * @param prods
   */
  async deleteSalesProds(ctx, tenantCode, prods) {

    _.map(prods, async prod => {
      const { materials } = prod;
      _.map(materials, async material => {
        const { usedMaterialRecord = [] } = material;
        _.map(usedMaterialRecord, async item => {
          const { _useCount = 0, pmLotId, } = item;
          if (_useCount > 0) {
            console.log('delete sales prods', _useCount);
            const res1 = await ctx.app.dbs.updateOne('ProcureMaterialRecord', {
              pmLotId,
              tenantCode
            }, { $inc: { useCount: -_useCount } });
          }
        });
      });
    });
  }

  /**
   * 创建订单商品，包括物料占用
   * @param ctx
   * @param tenantCode
   * @param code
   * @param prods
   * @returns {Promise<void>}
   */
  async createSalesProds(ctx, tenantCode, code, prods) {
    // console.log('createSalesProds', prods.length);
    _.map(prods, async prod => {
      const { materials = [], laborFee } = prod;
      prod.salesOrderCode = code;
      prod.tenantCode = tenantCode;
      const result = await ctx.app.dbs.insert('SalesProdRecord', prod);
      console.log('materials', materials.length);
      _.map(materials, async material => {
        const { usedProcureMaterialLots = [] } = material;

        _.map(usedProcureMaterialLots, async item => {
          const { usedCount = 0, code, pmLotId, } = item;
          console.log('usedCount', usedCount);
          if (usedCount > 0) {
            console.log('updateOne sales ProcureMaterialRecord', usedCount);
            const res1 = await ctx.app.dbs.updateOne('ProcureMaterialRecord', { pmLotId }, { $inc: { useCount: usedCount } });

            const store = await ctx.app.dbs.findOne('Material', { code, tenantCode });
            if (store) {
              const { storeCount = 0 } = store;
              const c = storeCount - usedCount;
              const res = await ctx.app.dbs.updateOne('Material', { code, tenantCode }, { storeCount: c });
            }
          }
        });
      });
    });
  }

  async payReview(body) {
    const { ctx, service } = this;
    const { tenantCode, code } = body;
    const result = await ctx.app.dbs.updateOne(table, { tenantCode, code }, body);
    return { status: 'ok', result };
  }

  async review(body) {
    const { ctx, service } = this;
    const { tenantCode, code, reviewStatus, createUser, createUsername, createdTs } = body;
    console.log('reviewStatus', body);
    const result = await ctx.app.dbs.updateOne(table, { tenantCode, code }, { reviewStatus });
    const order = await ctx.app.dbs.findOne(table, { tenantCode, code });
    const { tenantName } = order;
    const history = {
      table,
      name: '审核订单' + reviewStatus,
      oldData: order,
      tenantCode,
      code,
      tenantName,
      createUser,
      createUsername,
      createdTs
    };
    const historyRes = await ctx.app.dbs.insert('History', history);
    if (reviewStatus === '驳回') {
      const res = await service['outboundService'].deleteOne({ tenantCode, salesOrderCode: code });
      return { status: 'ok', result };
    }


    /**
     * 创建入库单
     */
    order.salesOrderCode = code;
    delete order['_id'];
    const result1 = await service['outboundService'].createOutboundOrder(order);
    return { status: 'ok', result };
  }

  async history(body) {
    const { tenantCode, code } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.find('History', { table: 'SalesOrder', tenantCode, code });
    return { status: 'ok', result };
  }

  async exportExcel(body) {
    const { ctx } = this;
    const res = await this.findOrderMany(body);
    const { result } = res;
    const mod = ctx.model['SalesOrder'];
    const _header = mod.schema.obj;
    delete _header['tenantName'];
    delete _header['tenantCode'];
    delete _header['createUser'];
    delete _header['createUsername'];
    delete _header['isDeleted'];
    delete _header['isEnabled'];
    delete _header['materialBody'];
    delete _header['labels'];
    delete _header['outboundCodes'];
    delete _header['outboundTime'];

    const header = [];
    _.map(_header, (item, key) => {
      item.title = item.desc;
      item.dataIndex = key;
      item.key = key;
      header.push(item);
    });
    console.log('excell', result);
    return { status: 'ok', result: { header, data: result } };
  }

  async uploadExcel(body) {
    const { ctx } = this;
    let { tenantCode, excelJson, table, createUser, createUsername, tenantName } = body;
    // console.log('bodyy', body);
    const modelStr = table.charAt(0)
      .toUpperCase() + table.slice(1);
    const mod = ctx.model[modelStr];
    const schema = mod.schema.obj;
    const _model = {};
    _.map(schema, (item, key) => {
      const { desc } = item;
      _model[desc] = key;
    });

    _.map(excelJson, async json => {
      const data = {};
      _.map(schema, async (item, key) => {
        const { desc, inputType } = item;
        data[key] = json[desc];
        if (inputType === 'switch') {
          data[key] = json[desc] === '是';
        }
        if (key === 'customerCode') {
          const customer = await ctx.app.dbs.findOne('Customer', { name: json['客户'] });
          data[key] = customer ? customer.code : data[key];
        }
      });

      // _.map(_model, (value, key) => {
      //   data[value] = item[key];
      // });
      const code = _stringUtils.getCode('SAL');
      data.code = code;
      data.tenantCode = tenantCode;
      data.createUser = createUser;
      data.createUsername = createUsername;
      data.tenantName = tenantName;
      data.reviewStatus = '待审核';
      data.createType = '导入';

      const res = await ctx.app.dbs.insert(modelStr, data);
      const history = {
        table,
        name: '导入订单',
        oldData: data,
        tenantCode,
        code,
        tenantName,
        createUser,
        createUsername,
      };
      const historyRes = await ctx.app.dbs.insert('History', history);
    });

    return { status: 'ok' };
  }

  // async findStatisticsMany(body) {
  //   const { ctx } = this;
  //   let { tenantCode, customerCode, division } = body;
  //   // const users = await ctx.app.dbs.aggregate('User', [
  //   //   { $match: { ...body } },
  //   //   { $sort: { ...sort } },
  //   //   { $skip: skip },
  //   //   { $limit: limit },
  //   // ]);
  //   const result = [];
  //   const query = [ {
  //     $group: {
  //       '_id': { customer: '$customer', customerCode: '$customerCode', division: '$division' },
  //       list: { $push: '$$ROOT' }
  //     }
  //   } ];
  //
  //   const res = await ctx.app.dbs.aggregate('SalesOrder', query);
  //
  //   _.map(res, (item, key) => {
  //     const { _id, list } = item;
  //     let _invoiceAmount = 0,
  //       _amount = 0,
  //       _outboundAmount = 0;
  //     _.map(list, (item, key) => {
  //       const { prods, amount = 0, outboundAmount = 0 } = item;
  //       _amount += amount;
  //       _outboundAmount += outboundAmount;
  //       _.map(prods, (prod) => {
  //         const { price = 0, outboundCount = 0, invoicingDate, count } = prod;
  //         if (invoicingDate) {
  //           _invoiceAmount += price * count;
  //         }
  //
  //       });
  //     });
  //
  //     _id.outboundAmount = _outboundAmount;
  //     _id.amount = _amount;
  //     _id.invoiceAmount = _invoiceAmount;
  //     result.push(_id);
  //   });
  //
  //   const res1 = await ctx.app.dbs.aggregate('Receipt', [ {
  //     $group: {
  //       '_id': { _accountName: '$_accountName', customer: '$customer' },
  //       list: { $push: '$$ROOT' }
  //     }
  //   } ]);
  //   _.map(res1, item => {
  //     const { _id, list } = item;
  //     let _receiptPayment = 0;
  //     _.map(list, (it, key) => {
  //       const { receiptAmount = 0 } = it;
  //       _receiptPayment += receiptAmount;
  //     });
  //
  //     const { _accountName, customer } = _id;
  //     const temp = _.find(result, it => {
  //       return it.customer === customer && it.division === _accountName;
  //     });
  //     console.log('tempd', temp);
  //     if (temp) temp.receiptAmount = _receiptPayment;
  //   });
  //
  //   return { status: 'ok', result };
  // }

  /**
   * 退补货
   */
  async findReturnGoodsOrderMany(body) {
    const { ctx } = this;
    const { key, customer, prodCode, prodName, tenantCode, salesOrderCode, spLotId, createdTs } = body;

    const query = { tenantCode };
    const _key = key ? key : 'createdTs';
    if (createdTs && createdTs.length > 0) {
      query['createdTs'] = {
        $gte: new Date(moment(createdTs[0])
          .valueOf()),
        $lt: new Date(moment(createdTs[1])
          .valueOf())
      };
    }

    const sort = {};
    sort[_key] = -1;

    if (spLotId) query['spLotId'] = { $regex: spLotId };
    if (customer) query['customer'] = { $regex: customer };
    if (prodCode) query['prodCode'] = { $regex: prodCode };
    if (prodName) query['prodName'] = { $regex: prodName };
    if (salesOrderCode) query['salesOrderCode'] = { $regex: salesOrderCode };

    const list = await ctx.app.dbs.find('SalesReturnGoodsOrder', query, sort);
    const countRes = await this.app.dbs.aggregate('SalesReturnGoodsOrder', [
      { $match: { ...query } },
      { $group: { _id: null, count: { $sum: '$returnCount' } } },

    ]);
    const assessRes = await this.app.dbs.aggregate('SalesReturnGoodsOrder', [
      { $match: { ...query } },
      {
        $project: {
          totalPrice: { $multiply: [ '$returnCount', '$price' ] }
        }
      },
      {
        $group: {
          _id: null, // 使用null表示不需要分组，直接累加所有文档
          amount: { $sum: '$totalPrice' } // 对totalPrice字段进行累加
        }
      }
    ]);
    const count = countRes.length > 0 ? countRes[0].count : 0;
    const amount = assessRes.length > 0 ? assessRes[0].amount : 0;
    console.log('assess res', assessRes);
    return { status: 'ok', result: { list, count, amount } };
  }

  async deleteReturnGoodsOrder(body) {
    const { tenantCode, _id } = body;
    const { ctx } = this;
    console.log('deleteReturnGoodsOrder', body);
    const result = await ctx.app.dbs.deleteOne('SalesReturnGoodsOrder', { tenantCode, _id });
    const { materialLots = [] } = body;
    _.map(materialLots, async item => {
      const { lotCode, code, lotCount } = item;
      const result = await ctx.app.dbs.deleteOne('InboundLot', { tenantCode, lotCode });
      /**
       * 物料库存
       */
      const res2 = await ctx.app.dbs.updateOne('Material', {
        code,
        tenantCode
      }, { $inc: { storeCount: -lotCount } });
    });
    return { status: 'ok', result };
  }

  async createReturnGoodsOrder(body) {
    const { ctx, service } = this;
    delete body['_id'];

    /**
     * 订单中的原料自动创建库存批次
     */
    const { outboundCount, returnCount } = body;
    const { materialLots = [], pkgLots = [] } = body;

    _.map(materialLots, lot => {
      const { materialContent = 0, materialCount, } = lot;
      //用占比和退货数量，计算释放入库的原料
      lot.inboundCount = returnCount * materialContent / 100;
      lot.lotType = '订单退货入库';
      lot.lotCode = 'RTI' + moment()
        .format('YYYY-MM-DDHHmmss');
      service.inboundService.createInboundLot(lot);

    });
    const result = await ctx.app.dbs.insert('SalesReturnGoodsOrder', body);
    return { status: 'ok', result };
  }

  async updateReturnGoodsOrder(body) {
    const { tenantCode, orderCode, returnCount, returnShippingFee = 0 } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.updateOne('SalesReturnGoodsOrder', { tenantCode, orderCode }, {
      returnCount,
      returnShippingFee
    });
    return { status: 'ok', result };
  }

  async findReturnGoodsOrder(body) {
    const { tenantCode, orderCode, returnCount } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.findOne('SalesReturnGoodsOrder', { tenantCode, orderCode });
    return { status: 'ok', result };
  }

  async findReplenishRecordMany(body) {
    const { ctx } = this;
    const { key, customer, prodCode, prodName, tenantCode, salesOrderCode, createdTs } = body;
    const query = { tenantCode };
    const _key = key ? key : 'createdTs';
    if (createdTs && createdTs.length > 0) {
      query['createdTs'] = {
        $gte: new Date(moment(createdTs[0])
          .valueOf()),
        $lt: new Date(moment(createdTs[1])
          .valueOf())
      };
    }

    const sort = {};
    sort[_key] = -1;

    if (customer) query['customer'] = { $regex: customer };
    if (prodCode) query['prodCode'] = { $regex: prodCode };
    if (prodName) query['prodName'] = { $regex: prodName };
    if (salesOrderCode) query['salesOrderCode'] = { $regex: salesOrderCode };

    const list = await ctx.app.dbs.find('SalesReplenishRecord', query);
    const countRes = await this.app.dbs.aggregate('SalesReplenishRecord', [
      { $match: { ...query } },
      { $group: { _id: null, count: { $sum: '$count' } } },

    ]);
    const assessRes = await this.app.dbs.aggregate('SalesReplenishRecord', [
      { $match: { ...query } },
      {
        $project: {
          totalPrice: { $multiply: [ '$count', '$price' ] }
        }
      },
      {
        $group: {
          _id: null, // 使用null表示不需要分组，直接累加所有文档
          amount: { $sum: '$totalPrice' } // 对totalPrice字段进行累加
        }
      }
    ]);
    const count = countRes.length > 0 ? countRes[0].count : 0;
    const amount = assessRes.length > 0 ? assessRes[0].amount : 0;
    console.log('assess res', assessRes);
    return { status: 'ok', result: { list, count, amount } };
  }

  async deleteReplenishRecord(body) {
    const { tenantCode, code } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.findOne(table, { tenantCode, code });
    // console.log('find sales order body', body);
    // result.prods = await ctx.app.dbs.find('ProdSalesRecord', { tenantCode, salesOrderCode: code });

    return { status: 'ok', result };
  }

  async createReplenishRecord(body) {
    const { tenantCode, code } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.insert('SalesReplenishRecord', body);

    return { status: 'ok', result };
  }

  async updateReplenishRecord(body) {
    const { tenantCode, code } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.updateOne(table, { tenantCode, code });
    // console.log('find sales order body', body);
    // result.prods = await ctx.app.dbs.find('ProdSalesRecord', { tenantCode, salesOrderCode: code });

    return { status: 'ok', result };
  }

  async findReplenishRecord(body) {
    const { tenantCode, orderCode } = body;
    const { ctx } = this;
    const result = await ctx.app.dbs.findOne(table, { tenantCode, orderCode });
    return { status: 'ok', result };
  }

  async findSalesProdMany(body) {
    const { ctx } = this;
    const {
      key,
      customer,
      prodCode,
      prodName,
      salesOrderCode,
      tenantCode,
      createdTs,
      isMaterialLotUsed,
      isPkgLotUsed, isInvoice
    } = body;
    const query = { tenantCode };
    const _key = key ? key : 'createdTs';
    if (createdTs && createdTs.length > 0) {
      query['createdTs'] = {
        $gte: new Date(moment(createdTs[0])
          .valueOf()),
        $lt: new Date(moment(createdTs[1])
          .valueOf())
      };
    }

    const sort = {};
    sort[_key] = -1;

    if (salesOrderCode) query['salesOrderCode'] = { $regex: salesOrderCode };
    if (customer) query['customer'] = { $regex: customer };
    if (prodCode) query['prodCode'] = { $regex: prodCode };
    if (prodName) query['prodName'] = { $regex: prodName };
    if (isPkgLotUsed && isPkgLotUsed === '未占用') query['pkgLots'] = { $size: 0 };
    if (isPkgLotUsed && isPkgLotUsed === '已占用') query['pkgLots'] = { $exists: true, $ne: [] };
    if (isMaterialLotUsed && isMaterialLotUsed === '未占用') query['materialLots'] = { $size: 0 };
    if (isMaterialLotUsed && isMaterialLotUsed === '已占用') query['materialLots'] = { $exists: true, $ne: [] };
    if (isInvoice && isInvoice === '未开票') query['invoicingCount'] = { $eq: 0 };
    if (isInvoice && isInvoice === '已开票') query['invoicingCount'] = { $gte: 0 };
    query['isDeleted'] = false;
    const result = await ctx.app.dbs.find('SalesProdRecord', query);

    return { status: 'ok', result };
  }

  async findSalesProd(body) {
    const { ctx } = this;
    const { tenantCode, spLotId } = body;
    // console.log('create sales prod', body);
    const result = await ctx.app.dbs.findOne('SalesProdRecord', { tenantCode, spLotId });
    return { status: 'ok', result };
  }

  async createSalesProd(body) {
    const { ctx } = this;
    const { tenantCode, salesOrderCode, prodCode = '' } = body;
    // console.log('create sales prod', body);

    const order = await ctx.app.dbs.findOne('SalesOrder', { tenantCode, code: salesOrderCode });
    const { prods, customer, division } = order;
    body.customer = customer;
    body.division = division;
    /**
     * 占用库存
     */
    body.spLotId = 'SPD' + moment()
      .format('YYYYMMDDHHmmss');
    const res1 = await this.usedLot(body);

    prods.push(body);
    const res = await ctx.app.dbs.updateOne('SalesOrder', { tenantCode, code: salesOrderCode }, { prods });

    const result = await ctx.app.dbs.insert('SalesProdRecord', body);
    this.addProdNumber(prodCode);
    return { status: 'ok', result };
  }

  /**
   * 解除占用入库批次
   * @param prod
   * @returns {Promise<void>}
   */
  async unusedLot(prod) {
    const { ctx } = this;
    const { materialLots = [], pkgLots = [], salesOrderCode, tenantCode, } = prod;
    _.map(materialLots, async material => {
      const { lotCode, code, materialCount, spLotId } = material;
      const res1 = await ctx.app.dbs.deleteOne('StoreLotUsed', {
        tenantCode,
        salesOrderCode,
        lotCode,
        spLotId
      });
      const res2 = await ctx.app.dbs.updateOne('InboundLot', {
        lotCode,
        tenantCode
      }, { $inc: { usedCount: -materialCount } });

      console.log('更新Material物料库存数量', material.name, materialCount);
      const res3 = await ctx.app.dbs.updateOne('Material', {
        code,
        tenantCode
      }, { $inc: { storeCount: materialCount } });

    });
    _.map(pkgLots, async item => {
      const { lotCode, materialCount, code, pmLotId } = item;
      const res1 = await ctx.app.dbs.deleteOne('StoreLotUsed', {
        tenantCode,
        salesOrderCode,
        lotCode,
        pmLotId
      });
      const res2 = await ctx.app.dbs.updateOne('InboundLot', {
        lotCode,
        tenantCode
      }, { $inc: { usedCount: -materialCount } });
      const res3 = await ctx.app.dbs.updateOne('Material', {
        code,
        tenantCode
      }, { $inc: { storeCount: materialCount } });
    });
  }

  /**
   * 占用入库批次
   * @param prod
   * @returns {Promise<void>}
   */
  async usedLot(prod) {
    const { ctx } = this;
    const { tenantCode, salesOrderCode, materialLots = [], spLotId, pkgLots = [] } = prod;
    /**
     *   materialLots: [
     *     {
     *       _id: '692529e0d1fe059124cac0c9',
     *       isDeleted: false,
     *       price: 20,
     *       fileList: [],
     *       inboundCount: 800,
     *       pmLotId: 'PML2025-11-25-11-59-44',
     *       code: 'MAT251125114919F2',
     *       name: '草酸1#',
     *       type: '466',
     *       subcategory: '液态',
     *       spec: 'SPEC1',
     *       number: 'A123BBB',
     *       createUser: 'chke',
     *       createUsername: '陈科',
     *       tenantCode: 'TEN2510300049342E',
     *       tenantName: '镇江新蓝化工',
     *       updatedTs: '2025-11-25T03:59:46.797Z',
     *       __v: 0,
     *       count: 1000,
     *       procureOrderCode: 'PRO1764043186772',
     *       vendor: '供应商中兴通讯',
     *       vendorCode: 'VEN2510311335580B',
     *       createdTs: '2025-11-25T03:59:46.797Z',
     *       inboundDate: '2025-11-25T04:00:30.032Z',
     *       checkInfo: [Object],
     *       lotType: '采购入库',
     *       lotCode: 'INT1764043232364',
     *       materialContent: 10,
     *       materialCount: 10
     *     }
     *   ],
     */
    _.map(materialLots, async material => {
      const { lotCode, materialCount, code } = material;
      material.salesOrderCode = salesOrderCode;
      material.recordId = 'SLU' + moment()
        .format('YYYY-MM-DDHHmmss');
      material.spLotId = spLotId;

      delete material._id;
      const res = await ctx.app.dbs.insert('StoreLotUsed', material);
      const res2 = await ctx.app.dbs.updateOne('InboundLot', {
        lotCode,
        tenantCode
      }, { $inc: { usedCount: materialCount } });

      const res3 = await ctx.app.dbs.updateOne('Material', {
        code,
        tenantCode
      }, { $inc: { storeCount: -materialCount } });
    });
    _.map(pkgLots, async item => {
      const { lotCode, materialCount, code } = item;
      item.salesOrderCode = salesOrderCode;
      item.recordId = 'SLU' + moment()
        .format('YYYY-MM-DDHHmmss');
      item.spLotId = spLotId;

      delete item._id;
      const res = await ctx.app.dbs.insert('StoreLotUsed', item);
      const res2 = await ctx.app.dbs.updateOne('InboundLot', {
        lotCode,
        tenantCode
      }, { $inc: { usedCount: materialCount } });
      const res3 = await ctx.app.dbs.updateOne('Material', {
        code,
        tenantCode
      }, { $inc: { storeCount: -materialCount } });
    });
  }

  async deleteSalesProd(body) {
    const { ctx } = this;
    const { tenantCode, spLotId, salesOrderCode } = body;
    console.log('delete sales prod', tenantCode, spLotId, salesOrderCode);
    const prod = await ctx.app.dbs.findOne('SalesProdRecord', { spLotId, tenantCode });

    const res1 = await this.unusedLot(prod);

    const order = await ctx.app.dbs.findOne('SalesOrder', { tenantCode, code: salesOrderCode });
    if (order) {
      const { prods } = order;
      _.remove(prods, item => {
        return item.spLotId === spLotId;
      });
      const res = await ctx.app.dbs.updateOne('SalesOrder', { tenantCode, code: salesOrderCode }, { prods });
    }

    const result = await ctx.app.dbs.deleteOne('SalesProdRecord', { spLotId, tenantCode });
    return { status: 'ok', result };
  }


  async updateSalesProd(body) {
    const { ctx } = this;
    const res = await this.deleteSalesProd(body);
    const result = await this.createSalesProd(body);

    return { status: 'ok', result };
  }

  async findNumberTxt(body) {
    const { ctx } = this;
    return { status: 'ok', result: [ '111', '222', '333' ] };
  }
};
